package com.hackathon2012_03_04.ryokocial;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Query;

import com.google.appengine.api.datastore.Blob;
import com.google.appengine.api.images.Image;
import com.google.appengine.api.images.ImagesService;
import com.google.appengine.api.images.ImagesServiceFactory;
import com.google.appengine.api.images.Transform;

/**
 * {@link ThumbnailService}の実装。
 */
public class ThumbnailServiceImpl 
implements ThumbnailService {
    
    @Override
    public long create(
    		byte[] imageData,
    		String caption,
            String user,
            ArrayList<String> tags,
            double lat,
            double lng) {
        
        // ImageServiceを利用してサムネイルを作成。
        ImagesService imagesService = ImagesServiceFactory.getImagesService();
        Image image = ImagesServiceFactory.makeImage(imageData);
        Blob original = new Blob(image.getImageData());
        Blob small = createThumbnail( image.getImageData(), Size.SMALL, imagesService );
        
        // サムネイルをデータストアに保存
        PersistenceManager pm = null;
        try {
            pm = createPersistenceManager();
            Thumbnail thumbnail =new Thumbnail(original, small, 
            		image.getFormat().name(), new Date(), 
            		caption, user, tags, lat, lng);
            	
            pm.makePersistent(thumbnail);
            return thumbnail.getId(); // IDを返却
        } finally {
            if ( pm != null ) pm.close();
        }
    }
    
    /**
     * 画像を取得するメソッド
     */
    @Override
    public Thumbnail getById(long id) {
        PersistenceManager pm = null;
        try {
            pm = createPersistenceManager();
            return pm.getObjectById(Thumbnail.class, id);
        } finally {
            if ( pm != null ) pm.close();
        }
    }
    @Override
	public Thumbnail getByPicName(String picname) {
		// TODO 自動生成されたメソッド・スタブ
		return null;
	}

	@Override
	public Thumbnail getByUser(String user) {
		// TODO 自動生成されたメソッド・スタブ
		return null;
	}

	@Override
	public Thumbnail getByTravel(String travel) {
		// TODO 自動生成されたメソッド・スタブ
		return null;
	}

	@Override
	public Thumbnail getByTag(String tag) {
		// TODO 自動生成されたメソッド・スタブ
		return null;
	}

	@Override
	public Thumbnail getByGeo(double lat, double lng) {
		// TODO 自動生成されたメソッド・スタブ
		return null;
	}
	
	//位置情報、キーワードから検索し、データクラスを返す
	@SuppressWarnings("unchecked")
	public List<Thumbnail> search(String keyword,int i){
		PersistenceManager pm =createPersistenceManager();
		Query query=pm.newQuery(Thumbnail.class);
		
		//何で検索するか分岐
		switch (i){
		case 0:
			/** 検索条件の設定 */
			//位置情報で検索することがウマク出来なかったので、全件取得してから位置を取得、絞り込みを行う。
			//オーダー
			query.setOrdering("createDate asc");
			if(keyword != null && keyword.length()!=0){
				//キーワードに合うタグを探す
				query.setFilter("tags == '"+keyword+"'");
			}
			break;
		case 1:
			/** 検索条件の設定 */
			//どの旅行かで検索
			query.setOrdering("createDate asc");
			if(keyword != null && keyword.length()!=0){
				//キーワードに合うものを探す
				query.setFilter("travel == '"+keyword+"'");
			}
			break;
		}
		
		
		
		
		
		List<Thumbnail> thumbnails=(List<Thumbnail>)query.execute();
		return thumbnails;
	}
	
    
    /**
     * サムネイル画像を生成する。生成規則は以下のとおり。
     * <ol>
     *   <li>縦横の比率を保ったまま、短辺にあわせてリサイズ</li>
     *   <li>中心部をトリミング</li>
     * </ol>
     * @param image 元画像
     * @param size サムネイルサイズ
     * @param imagesService {@link ImagesService}
     * @return 生成した画像データ(PNG形式)
     */
    private Blob createThumbnail( byte[] imageData, Size size, ImagesService imagesService ) {
        // 縦横の比率を保ったまま短辺にあわせてリサイズ後、中心部をトリミング
        Image image = ImagesServiceFactory.makeImage(imageData);
        List<Transform> ts = new ArrayList<Transform>();
        float wr = ((float) size.width ) / image.getWidth();
        float hr = ((float) size.height ) / image.getHeight();
        if ( wr > hr  ) {
            float nh =  image.getHeight()*wr;
            float r =  (1.0F - ((float) size.height ) / nh ) /2;
            ts.add(ImagesServiceFactory.makeResize( size.width, (int) Math.floor( nh ) ));
            ts.add(ImagesServiceFactory.makeCrop( 0, r, 1.0, 1.0-r ));
        } else {
            float nw =  image.getWidth()*hr;
            float r =  (1.0F - ((float) size.width ) / nw ) /2;
            ts.add(ImagesServiceFactory.makeResize( (int) Math.floor( nw ), size.height ));
            ts.add(ImagesServiceFactory.makeCrop( r, 0, 1.0-r, 1.0 ));
        }
        Transform t = ImagesServiceFactory.makeCompositeTransform(ts);
        Image thumbnail = imagesService.applyTransform(t, image);
        return new Blob(thumbnail.getImageData());
    }

    /**
     * {@link PersistenceManager}を取得する。
     * @return {@link PersistenceManager}
     */
    private static PersistenceManager createPersistenceManager() {
        synchronized( ThumbnailServiceImpl.class ) {
            if (pmfInstance == null) pmfInstance = JDOHelper.getPersistenceManagerFactory("transactions-optional");
            return pmfInstance.getPersistenceManager();
        }
    }
    /**
     * {@link PersistenceManagerFactory}
     */
    private static PersistenceManagerFactory pmfInstance = null;
	
}
